package kernel_gui.gui.extended;

import java.awt.Component;
import java.awt.event.ActionEvent;
import java.util.List;

import javax.swing.DefaultComboBoxModel;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.table.DefaultTableModel;

import kernel_gui.gui.generic.graphic.ControlQuestions;

import common.entities.enums.PATTERN;
import common.entities.persistent.DBQuestion;
import common.entities.persistent.Movie;

@SuppressWarnings("serial")
public class EControlQuestions extends ControlQuestions {

	private DefaultComboBoxModel<PATTERN> patternsModel;
	private PATTERN selectedPattern;
	
	private String partOf1Str = null;
	private String partOf2Str = null;
	private int partOf1Int = -1;
	private int partOf2Int = -1;
	
	private int count = 0;
	private int numberOfRecordsPerPage;
	private int currentPage = 0;
	private int totalPages = 0;
	
	private List<DBQuestion> currentDataInTableModel;
	private DefaultTableModel currentTableModel = new DefaultTableModel();
	
	
	@SuppressWarnings("unchecked")
	public EControlQuestions(){
		/*Command to execute on cancel*/
		setExecuteOnCancel(new CommandToExecute() {
			
			@Override
			public void command(Object answer) {
				Component components[] = MainPanel.getComponents();
				for (Component c : components) {
					if(c instanceof JPanel){
						JPanel panel = (JPanel) c;
						Component pcomponents[] = panel.getComponents();
						for(Component pc : pcomponents){
							if(pc instanceof JPanel){
								JPanel anotherPanel = (JPanel) pc;
								Component pccomponents[] = anotherPanel.getComponents();
								for(Component pcc : pccomponents){
									pcc.setEnabled(true);
								}
							}
							pc.setEnabled(true);
						}
					}
					c.setEnabled(true);
				}
				ResultTable.setEnabled(true);
			}
		});
		
		/*Command to execute before long request*/
		setExecuteBeforeLongRequest(new CommandToExecute() {
			
			@Override
			public void command(Object answer) {
				Component components[] = MainPanel.getComponents();
				for (Component c : components) {
					if(c instanceof JPanel){
						JPanel panel = (JPanel) c;
						Component pcomponents[] = panel.getComponents();
						for(Component pc : pcomponents){
							if(pc instanceof JPanel){
								JPanel anotherPanel = (JPanel) pc;
								Component pccomponents[] = anotherPanel.getComponents();
								for(Component pcc : pccomponents){
									pcc.setEnabled(false);
								}
							}
							pc.setEnabled(false);
						}
					}
					c.setEnabled(false);
				}
				ResultTable.setEnabled(false);
			}
		});
		
		/*init the ddb with Patterns*/
		patternsModel = new DefaultComboBoxModel<PATTERN>(PATTERN.values());
		choosePatternComboBox.setModel(patternsModel);
		updateChoosenPattern();
		
		/*Update the numberOfRecords variable*/
		NumOfRecordsInPageComboBox.setSelectedIndex(2);
		numberOfRecordsPerPage = Integer.parseInt(NumOfRecordsInPageComboBox.getSelectedItem().toString());
		
		/*Create defaultive model*/
		currentTableModel = new DefaultTableModel(new Object [][] {},new String [] {
                "Question","Level", "Right Answer", "Wrong Answer 1", "Wrong Answer 2", "Wrong Answer 3"
            });
		ResultTable.setModel(currentTableModel);
		updateButtonsAndLabelsAfterReturnedResultSet();
	}
	
	protected void countResultAndPopulateTable(int page){
		
		final int pageWhenFinished = page;
		/*Command to execute after returning from*/
		int requestID = executeBeforeLongRequest(new CommandToExecute() {
			
			@Override
			public void command(Object answer) {
				/*Updated count & labels*/
				EControlQuestions.this.count = Integer.parseInt(answer.toString());
				EControlQuestions.this.FoundNumberLabel.setText(numbers_nf.format(EControlQuestions.this.count));
				
				if(EControlQuestions.this.count != 0)
					EControlQuestions.this.currentPage = 1;
				else
					EControlQuestions.this.currentPage = 0;
				
				EControlQuestions.this.PageNumberLabel.setText(numbers_nf.format(EControlQuestions.this.currentPage));
				EControlQuestions.this.totalPages = (int) Math.ceil(((float)EControlQuestions.this.count)/numberOfRecordsPerPage);
				EControlQuestions.this.TotalPageNumberLabel.setText(numbers_nf.format(EControlQuestions.this.totalPages));
									
				/*Get the data*/
				populateTableWithResults(pageWhenFinished);
				
			}
		});
	
		switch(selectedPattern){
		case ACTOR_PLAYED_IN_MOVIE:
			kernel.countQuestionMovie(selectedPattern, partOf1Str, requestID);
			break;
		case GENRE_OF_MOVIE:
			kernel.countQuestionMovie(selectedPattern, partOf1Str, requestID);
			break;
		case MOVIE_ACTOR_IN:
			kernel.countQuestioPerson(selectedPattern, partOf1Str, partOf2Str, requestID);
			break;
		case MOVIE_DIRECTED_BY:
			kernel.countQuestioPerson(selectedPattern, partOf1Str, partOf2Str, requestID);
			break;
		case MOVIE_RELEASED_IN_YEAR:
			kernel.countQuestioYear(selectedPattern, partOf1Int, partOf2Int, requestID);
			break;
		}

	}
	
	private void populateTableWithResults(int page){
		/*Command to execute after returning from*/
		
		final int pageNumberToSet = page;
		int requestID = executeBeforeLongRequest(new CommandToExecute() {
			
			@SuppressWarnings("unchecked")
			@Override
			public void command(Object answer) {
				if(answer != null){
					EControlQuestions.this.currentDataInTableModel = (List<DBQuestion>) answer;
					
					/*Create new table model, and insert the rows*/
					currentTableModel = new DefaultTableModel(new Object [][] {},
							new String [] {
			                "Question", "Level", "Right Answer", "Wrong Answer 1", "Wrong Answer 2", "Wrong Answer 3"
		            });
					
					/*Add the result data to the table model*/
					for(int i = 0; i < EControlQuestions.this.currentDataInTableModel.size(); i++){
						DBQuestion question = EControlQuestions.this.currentDataInTableModel.get(i);
						String ql;
						switch(question.getQuestionLevel()){
							case 1:
								ql = "Easy";
								break;
							case 2:
								ql = "Medium";
								break;
							case 3:
								ql = "Hard";
								break;
							default:
								ql = ">>UNKNOWN<<";
								break;
						}
						
						String[] temp_ans = question.getAnswers();
						if(question.getRightAnswerId() != 0){
							String tmp = temp_ans[0];
							temp_ans[0] = temp_ans[question.getRightAnswerId()];
							temp_ans[question.getRightAnswerId()] = tmp;
						}
						
						String r = question.getAnswers()[0];
						String w1 = question.getAnswers()[1];
						String w2 = question.getAnswers()[2];
						String w3 = question.getAnswers()[3];
						
						

						Object[] rowData = new Object[] {question.getQuestion(), ql, r, w1, w2, w3};
						currentTableModel.insertRow(i, rowData);
					}
					
					
					/*Set the table model and the first page of it*/
					ResultTable.setModel(currentTableModel);
					if(EControlQuestions.this.count != 0)
						currentPage = pageNumberToSet;
					else
						currentPage = 0;
					
					updateButtonsAndLabelsAfterReturnedResultSet();
				}
			}
		});
		
		int from = (page <= 0) ? 0 : (page-1)*numberOfRecordsPerPage;
		int to = (page <= 0) ? 0 : page*numberOfRecordsPerPage;
		
		switch(selectedPattern){
			case ACTOR_PLAYED_IN_MOVIE:
				kernel.searchQuestionMovie(selectedPattern, partOf1Str, from, to, requestID);
				break;
			case GENRE_OF_MOVIE:
				kernel.searchQuestionMovie(selectedPattern, partOf1Str, from, to, requestID);
				break;
			case MOVIE_ACTOR_IN:
				kernel.searchQuestioPerson(selectedPattern, partOf1Str, partOf2Str, from, to, requestID);
				break;
			case MOVIE_DIRECTED_BY:
				kernel.searchQuestioPerson(selectedPattern, partOf1Str, partOf2Str, from, to, requestID);
				break;
			case MOVIE_RELEASED_IN_YEAR:
				kernel.searchQuestioYear(selectedPattern, partOf1Int, partOf2Int, from, to, requestID);
				break;
			}
		}
	
/*Table Panel*/
	
	private void updateButtonsAndLabelsAfterReturnedResultSet(){
		EControlQuestions.this.PageNumberLabel.setText(String.valueOf(EControlQuestions.this.currentPage));
		EControlQuestions.this.totalPages = (int) Math.ceil(((float)EControlQuestions.this.count)/numberOfRecordsPerPage);
		EControlQuestions.this.TotalPageNumberLabel.setText(String.valueOf(EControlQuestions.this.totalPages));
		
		if(totalPages == 0){
			NextButton.setEnabled(false);
			PreviousButton.setEnabled(false);
			NumOfRecordsInPageComboBox.setEnabled(false);
		}else{
			NextButton.setEnabled(true);
			PreviousButton.setEnabled(true);
			NumOfRecordsInPageComboBox.setEnabled(true);
		}
					
	}

	@Override
	protected void NumOfRecordsInPageComboBoxActionPerformed(ActionEvent evt) {
		numberOfRecordsPerPage = Integer.parseInt(NumOfRecordsInPageComboBox.getSelectedItem().toString());
		
		/*fix problem when the user is on page 100 in 5rec-per-page but there is no page 100 in 100rec-per-page*/
		int expectedTotalPages = (int) Math.ceil(((float)EControlQuestions.this.count)/numberOfRecordsPerPage);

		
		if(currentPage > expectedTotalPages)
			currentPage = expectedTotalPages;
		
		populateTableWithResults(currentPage);

	}
	
	@Override
	protected void PreviousButtonActionPerformed(ActionEvent evt) {
		if(currentPage > 1){
			int askingPage = currentPage-1;
			populateTableWithResults(askingPage);
		}else{
			populateTableWithResults(totalPages);
		}
	}
	
	@Override
	protected void NextButtonActionPerformed(ActionEvent evt) {
		if(currentPage < totalPages){
			int askingPage = currentPage+1;
			populateTableWithResults(askingPage);
		}else{
			populateTableWithResults(1);
		}
	}
	
	@Override
	protected void DeleteButtonActionPerformed(ActionEvent evt) {
		int[] selectedRowIndexes = ResultTable.getSelectedRows();
		if(selectedRowIndexes.length != 1){
			JOptionPane.showMessageDialog(this, "Please select ONE record to delete");
		}else{
			/*Command to execute after returning from*/
			int requestID = executeBeforeLongRequest(new CommandToExecute() {
				
				@Override
				public void command(Object answer) {
					if(currentDataInTableModel.size() != 1)
						EControlQuestions.this.countResultAndPopulateTable(currentPage);
					else
						EControlQuestions.this.countResultAndPopulateTable(--currentPage);
				}
			});
			
			DBQuestion question = this.currentDataInTableModel.get(ResultTable.convertRowIndexToModel(selectedRowIndexes[0]));
			kernel.deleteQuestion(selectedPattern, question.getId(), requestID);
		}
	}

	private boolean getSearchVariablesData(){
		
		if(!PartOf1TextField.getText().equals(""))
			partOf1Str = PartOf1TextField.getText();
		else
			partOf1Str = null;
		
		if(!PartOf2TextField.getText().equals(""))
			partOf2Str = PartOf2TextField.getText();
		else
			partOf2Str = null;
		
		
		return true;
	}

	@Override
	protected void SearchButtonActionPerformed(ActionEvent evt) {
		boolean error = false;
		if(getSearchVariablesData()){
			if(selectedPattern == PATTERN.MOVIE_RELEASED_IN_YEAR){
				/*check user input*/
				int ui_yearFrom = -1;
				if(!(partOf1Str == null)){
					try{
						ui_yearFrom = Integer.parseInt(partOf1Str);
					}catch (NumberFormatException e) {
						/*prompt to user after*/
					}
					
					if(ui_yearFrom == -1){
						JOptionPane.showMessageDialog(this, "A year must consist only of numbers and be in this format: YYYY");
						error = true;
					}else if (ui_yearFrom < Movie.releaseYearMinValue || ui_yearFrom > Movie.releaseYearMaxValue){
						JOptionPane.showMessageDialog(this, "The number isn't between " + 
							Movie.releaseYearMinValue + "-" + Movie.releaseYearMaxValue + " (excluding).");
						error = true;
					}else{
						/*parsing succeeded*/
						partOf1Int = ui_yearFrom;
					}
				}else{
					partOf1Int = -1;
				}
				if(!error){
					int ui_yearTo = -1;
					if(!(partOf2Str == null) ){
						try{
							ui_yearTo = Integer.parseInt(partOf2Str);
						}catch (NumberFormatException e) {
							/*prompt to user after*/
						}
						
						if(ui_yearTo == -1){
							JOptionPane.showMessageDialog(this, "A year must consist only of numbers and be in this format: YYYY");
							error = true;
						}else if (ui_yearTo < Movie.releaseYearMinValue || ui_yearTo > Movie.releaseYearMaxValue){
							JOptionPane.showMessageDialog(this, "The number isn't between " + 
								Movie.releaseYearMinValue + "-" + Movie.releaseYearMaxValue + " (excluding).");
							error = true;
						}else{
							/*parsing succeeded*/
							partOf2Int = ui_yearTo;
						}
					}else{
						partOf2Int = ui_yearTo;
					}
				}
			}
			
			if(!error)			
				countResultAndPopulateTable(1);
		}
	}

	@Override
	protected void InsertButtonActionPerformed(ActionEvent evt) {
		openAnotherFrame(ECreateQuestion.class, true);

	}

	@Override
	protected void BackButtonActionPerformed(ActionEvent evt) {
		openAnotherFrame(EControlPanelMenuFrame.class, true);

	}

	@Override
	protected void choosePatternComboBoxActionPerformed(ActionEvent evt) {
		updateChoosenPattern();

	}
	
	private void updateChoosenPattern(){
		selectedPattern = (PATTERN)choosePatternComboBox.getSelectedItem();
		
		partOf1Int = -1;
		partOf1Str = null;
		partOf2Int = -1;
		partOf2Str = null;
		
		currentTableModel = new DefaultTableModel(new Object [][] {},
				new String [] {
                "Question", "Level", "Right Answer", "Wrong Answer 1", "Wrong Answer 2", "Wrong Answer 3"
        });
		
		switch(selectedPattern){
			case ACTOR_PLAYED_IN_MOVIE:{
				PartOf1Label.setText("Part Of Movie Title:");
				PartOf1TextField.setText("");
				PartOf2Label.setVisible(false);
				PartOf2TextField.setVisible(false);
				break;
			}case GENRE_OF_MOVIE:{
				PartOf1Label.setText("Part Of Movie Title:");
				PartOf1TextField.setText("");
				PartOf2Label.setVisible(false);
				PartOf2TextField.setVisible(false);
				break;
			}case MOVIE_ACTOR_IN:{
				PartOf1Label.setText("Part Of First Name:");
				PartOf1TextField.setText("");
				PartOf2Label.setVisible(true);
				PartOf2TextField.setVisible(true);
				PartOf2Label.setText("Part Of Last Name:");
				PartOf2TextField.setText("");
				break;
			}case MOVIE_DIRECTED_BY:{
				PartOf1Label.setText("Part Of First Name:");
				PartOf1TextField.setText("");
				PartOf2Label.setVisible(true);
				PartOf2TextField.setVisible(true);
				PartOf2Label.setText("Part Of Last Name:");
				PartOf2TextField.setText("");
				break;
			}case MOVIE_RELEASED_IN_YEAR:{
				PartOf1Label.setText("Year From:");
				PartOf1TextField.setText("");
				PartOf2Label.setVisible(true);
				PartOf2TextField.setVisible(true);
				PartOf2Label.setText("Year To:");
				PartOf2TextField.setText("");
				break;
			}
		}
	}

	@Override
	protected void setWindowComponentsWhenCalledFromAnotherFrame() {
		/*not needed*/

	}


}
